﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using StarlightEngine;

namespace StarlightEngine.Editor
{
    public enum MoveDirection
    {
        Up,
        Down,
        Left,
        Right
    }

    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class EditorGame : Microsoft.Xna.Framework.Game
    {
        public float PlacementScale = 1.0f, PlacementRotation = 0f;
        public Color PlacementColor = Color.Red;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Scene mainScene;
        MouseState current, last;
        KeyboardState kCur, kLast;

        public const int MoveSpeed = 10;


        public void SetZoom(float val)
        {
            EditorScene.ZoomLevel = val;
        }

        string currentTexture = "";

        public Scene EditorScene
        {
            get { return mainScene; }
        }

        

        public bool HasAddedNode = false;
        public bool AllowNodeCreation = false;
        
        
        Dictionary<string, string> textures
        {
            get { return mainScene.RequiredTextures; }
        }
        float scale = 1f;

       

        public Node LastNode
        {
            get { 
                return mainScene.LastAddedNode; }
        }

        string author = "", name = "";
        public string Author
        {
            get { return author; }
            set
            {
                author = value;
                mainScene.CreatorsName = value;
            }
        }
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                mainScene.Name = value;
            }
        }
       

        public string NodeToHighlight = "";
        

        public Dictionary<string, Node> Nodes
        {
            get { return mainScene.Nodes; }           
        }

        public EditorGame()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";            
        }

        public void Move(MoveDirection dir)
        {
            switch (dir)
            {
                case MoveDirection.Right:
                    SceneManager.ActiveScene.Move(new Vector2(MoveSpeed, 0));
                    break;

                case MoveDirection.Left:
                    SceneManager.ActiveScene.Move(new Vector2(-MoveSpeed, 0));
                    break;

                case MoveDirection.Down :
                    SceneManager.ActiveScene.Move(new Vector2(0, MoveSpeed));
                    break;

                case MoveDirection.Up:
                    SceneManager.ActiveScene.Move(new Vector2(0, -MoveSpeed));
                    break;

            }
        }

        public void ResetCameraPos()
        {
            SceneManager.ActiveScene.CameraPosition = Vector2.Zero;
        }

        public void ResetCameraRot()
        {
            SceneManager.ActiveScene.Rotation = 0f;
        }

        public void ResetCameraZoom()
        {
            SceneManager.ActiveScene.ZoomLevel = 1f;
        }

        public void ResetCamera()
        {
            ResetCameraPos();
            ResetCameraRot();
            ResetCameraZoom();
        }

        public void Load(string path)
        {
            mainScene.LoadFromFile(path);            
        }

        public void RemoveNode(string name)
        {
            NodeToHighlight = "";
            mainScene.Nodes.Remove(name);
        }

        public void LoadTexture(string name, string text)
        {
            string path = text.Replace("Content\\","");
            TextureManager.AddTexture(name, path);
            try
            {
                mainScene.RequiredTextures.Add(name, path);
            }
            catch (ArgumentException)
            {
                System.Windows.Forms.MessageBox.Show("Texture already exists.", "Warning", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
            }
            
        }

        public void Rotate(MoveDirection dir)
        {
            float moveSpeed = MathHelper.ToRadians(100);
            if (dir == MoveDirection.Up || dir == MoveDirection.Down)
                throw new Exception("Can't rotate up/down.");

            if (dir == MoveDirection.Left)
                SceneManager.ActiveScene.Rotate(-moveSpeed);
            else
                SceneManager.ActiveScene.Rotate(moveSpeed);
        }


        public void Save(string path)
        {
            mainScene.SaveToFile(path);
        }

        public void CreateTextures()
        {
            //Populate textures for use in editor            
        }

        public void SetTexture(string texture)
        {
            currentTexture = texture;
        }

        protected override void Initialize()
        {          

            base.Initialize();
        }

        protected override void LoadContent()
        {
            graphics.PreferredBackBufferWidth = 670;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();
            spriteBatch = new SpriteBatch(GraphicsDevice);            
            Engine.Initialize(this);            
            //TextureManager.Initialize();
            current = Mouse.GetState();
            kCur = Keyboard.GetState();
            mainScene = new Scene();            
            //Create a blank texture.
            TextureManager.CreateBlank(GraphicsDevice);            
            
            SceneManager.AddScene("LevelEditorScene", mainScene);
            SceneManager.SetActiveScene("LevelEditorScene");
            Settings.Editor = true;
        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            Engine.Update(gameTime);
            last = current;
            current = Mouse.GetState();
            kLast = kCur;
            kCur = Keyboard.GetState();
            
            if (kCur.IsKeyDown(Keys.F))
                this.Exit();



            if (current.LeftButton == ButtonState.Pressed && AllowNodeCreation && !HasAddedNode)
            {
                scale = this.PlacementScale;
                Node tmp = new SpriteNode(currentTexture);

                Vector2 MousePos = new Vector2((int)current.X, (int)current.Y);
                Vector2 pos = Vector2.Transform(MousePos, Matrix.Invert(Engine.CameraMatrix));
                Texture2D t = TextureManager.GetTexture(currentTexture);
                Vector2 text = new Vector2(t.Width / 2, t.Height / 2);
                text *= scale;
                Vector2 fixPos = pos - text;
                tmp.Position = fixPos;
                tmp.Scale = scale;
                tmp.DrawColor = Color.White;
                SceneManager.ActiveScene.AddNode("Node", tmp);
                HasAddedNode = true;
            }
            

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkGray);
            Engine.Draw(gameTime);
            spriteBatch.Begin();
            if (AllowNodeCreation)
            {
                //Quite hacky. :3
                //Draw the low alpha placement model.                 
                Vector2 pos = new Vector2((int)current.X, (int)current.Y);
                Texture2D t = TextureManager.GetTexture(currentTexture);
                Vector2 text = new Vector2(t.Width / 2, t.Height / 2);
                text *= PlacementScale;
                Vector2 fixPos = pos - text;
                Texture2D tmp = TextureManager.GetTexture(currentTexture);
                Rectangle drawTo = new Rectangle((int)fixPos.X, (int)fixPos.Y, (int)(tmp.Width * PlacementScale), (int)(tmp.Height * PlacementScale));                
                spriteBatch.Draw(t, drawTo, null, new Color(PlacementColor, 175), PlacementRotation, Vector2.Zero, SpriteEffects.None, .00001f);
            }           

            spriteBatch.End();
            
            if (NodeToHighlight != "")
            {
                Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.Texture,SaveStateMode.None,Engine.CameraMatrix);
                Color tmp = EditorScene.Nodes[NodeToHighlight].DrawColor;
                EditorScene.Nodes[NodeToHighlight].DrawColor = new Color(tmp, 130);
                EditorScene.Nodes[NodeToHighlight].Draw();
                EditorScene.Nodes[NodeToHighlight].DrawColor = tmp;
                //Now draw the highlight.
                Engine.SpriteBatch.Draw(TextureManager.GetTexture(""), EditorScene.Nodes[NodeToHighlight].Rectangle, null, new Color(Settings.NodeHighlightColor, 255 / 2), EditorScene.Nodes[NodeToHighlight].Rotation, EditorScene.Nodes[NodeToHighlight].Origin, SpriteEffects.None, 0.00000000000000000001f);
                Engine.SpriteBatch.End();               
            }
            try
            {
                base.Draw(gameTime);
            }
            catch (InvalidOperationException) { }
        }
    }
}
